using System;
using System.Collections.Generic;
using System.Text;
using CavemanTools.Extensions;

namespace CavemanTools.Sql
{
	/// <summary>
	/// Creates an sql string for updating a table
	/// </summary>
	public class UpdateQueryStringBuilder
	{
		private string _table;
		private IEnumerable<string> _columns;
		private string _condition;

		public UpdateQueryStringBuilder()
		{
			
		}

		public UpdateQueryStringBuilder(string table)
		{
			SetTable(table);
		}

		
		public UpdateQueryStringBuilder SetTable(string name)
		{
			if (string.IsNullOrEmpty(name)) throw new ArgumentNullException("name");
			_table = name;
			return this;
		}

		/// <summary>
		/// Sets the fields to update
		/// </summary>
		/// <param name="columnNames">Fields names</param>
		/// <returns></returns>
		public UpdateQueryStringBuilder UpdateFields(IEnumerable<string> columnNames)
		{
			if (columnNames == null) throw new ArgumentNullException("columnNames");
			_columns = columnNames;
			return this;
		}

		/// <summary>
		/// Sets the fields to update from object properties
		/// </summary>
		/// <param name="columns">Anonymous object</param>
		/// <returns></returns>
		public UpdateQueryStringBuilder UpdateFields(object columns)
		{
			return UpdateFields(columns.ToDictionary().Keys);			
		}

		/// <summary>
		/// Specify update condition, usually id=value
		/// </summary>
		/// <param name="condition">Sql condition</param>
		/// <returns></returns>
		public UpdateQueryStringBuilder Where(string condition)
		{
			if (string.IsNullOrEmpty(condition)) throw new ArgumentNullException("condition");
			_condition = condition;
			return this;
		}

		/// <summary>
		/// Returns the query string for Sql Server.
		/// </summary>
		/// <returns></returns>
		public override string ToString()
		{
			return ToString(new SqlParameterFormatter());
		}
		/// <summary>
		/// Returns the query string.
		/// </summary>
		/// <param name="formatter">Format parameter</param>
		/// <returns></returns>
		public string ToString(ISqlParameterFormatter formatter)
		{
			if (formatter == null) throw new ArgumentNullException("formatter");
			return ToString(formatter.Format);
		}

		/// <summary>
		/// Returns the query string.
		/// </summary>
		/// <param name="formatter">Format parameter delegate, should return formated parameter name for query</param>
		/// <returns></returns>
		public string ToString(Func<string,string> formatter)
		{
			if (formatter == null) throw new ArgumentNullException("formatter");
			var sb = new StringBuilder();
			sb.AppendFormat("update {0} set", _table);
			if (_columns == null) throw new NullReferenceException("Data can't be null");
			foreach (var column in _columns)
			{
				sb.AppendFormat(" {0}={1},", column, formatter(column));
			}
			sb.Remove(sb.Length - 1, 1);
			sb.AppendFormat(" where {0}", _condition);
			return sb.ToString();
		}
	}
}
